using Fiddler;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Net;
using System.IO;

namespace TangCaptureTraffic.Services
{
    /// <summary>
    /// 会话服务实现类，负责管理网络会话的存储和操作
    /// </summary>
    public class SessionService : ISessionService
    {
        private readonly ICollection<Session> _sessions = new List<Session>();
        private readonly ReaderWriterLockSlim _sessionsLock = new ReaderWriterLockSlim();
        private readonly IConfigurationService _configService;

        /// <summary>
        /// 会话添加事件
        /// </summary>
        public event Action<Session> SessionAdded;
        
        /// <summary>
        /// 会话完成事件
        /// </summary>
        public event Action<Session> SessionCompleted;

        public SessionService(IConfigurationService configService)
        {
            _configService = configService ?? throw new ArgumentNullException(nameof(configService));
        }

        /// <summary>
        /// 添加新会话
        /// </summary>
        /// <param name="session">要添加的会话</param>
        public void AddSession(Session session)
        {
            if (session == null) return;

            _sessionsLock.EnterWriteLock();
            try
            {
                // 检查是否需要清理旧会话
                if (_sessions.Count >= _configService.GetMaxSessions())
                {
                    CleanupOldSessionsInternal(_configService.GetSessionCleanupCount());
                }

                _sessions.Add(session);
                SessionAdded?.Invoke(session);
            }
            finally
            {
                _sessionsLock.ExitWriteLock();
            }
        }

        /// <summary>
        /// 标记会话完成
        /// </summary>
        /// <param name="session">完成的会话</param>
        public void CompleteSession(Session session)
        {
            if (session == null) return;
            SessionCompleted?.Invoke(session);
        }

        /// <summary>
        /// 获取所有会话
        /// </summary>
        /// <returns>会话集合的副本</returns>
        public IEnumerable<Session> GetAllSessions()
        {
            _sessionsLock.EnterReadLock();
            try
            {
                return _sessions.ToList();
            }
            finally
            {
                _sessionsLock.ExitReadLock();
            }
        }

        /// <summary>
        /// 根据ID获取会话
        /// </summary>
        /// <param name="sessionId">会话ID</param>
        /// <returns>会话对象，如果不存在则返回null</returns>
        public Session GetSessionById(int sessionId)
        {
            _sessionsLock.EnterReadLock();
            try
            {
                return _sessions.FirstOrDefault(s => s.id == sessionId);
            }
            finally
            {
                _sessionsLock.ExitReadLock();
            }
        }

        /// <summary>
        /// 清理旧会话
        /// </summary>
        /// <param name="count">要清理的会话数量</param>
        public void CleanupOldSessions(int count)
        {
            _sessionsLock.EnterWriteLock();
            try
            {
                CleanupOldSessionsInternal(count);
            }
            finally
            {
                _sessionsLock.ExitWriteLock();
            }
        }

        /// <summary>
        /// 内部清理方法（需要在写锁内调用）
        /// </summary>
        /// <param name="count">要清理的会话数量</param>
        private void CleanupOldSessionsInternal(int count)
        {
            var sessionsToRemove = _sessions.Take(count).ToList();
            foreach (var session in sessionsToRemove)
            {
                _sessions.Remove(session);
            }

            if (sessionsToRemove.Count > 0)
            {
                // 强制垃圾回收
                GC.Collect();
                System.Diagnostics.Debug.WriteLine($"已清理 {sessionsToRemove.Count} 个旧会话，当前会话数: {_sessions.Count}");
            }
        }

        /// <summary>
        /// 获取会话总数
        /// </summary>
        /// <returns>会话总数</returns>
        public int GetSessionCount()
        {
            _sessionsLock.EnterReadLock();
            try
            {
                return _sessions.Count;
            }
            finally
            {
                _sessionsLock.ExitReadLock();
            }
        }

        /// <summary>
        /// 清空所有会话
        /// </summary>
        public void ClearAllSessions()
        {
            _sessionsLock.EnterWriteLock();
            try
            {
                _sessions.Clear();
                GC.Collect();
                System.Diagnostics.Debug.WriteLine("已清空所有会话");
            }
            finally
            {
                _sessionsLock.ExitWriteLock();
            }
        }

        /// <summary>
        /// 重发会话请求
        /// </summary>
        /// <param name="session">要重发的会话</param>
        /// <returns>新的会话对象，失败时返回null</returns>
        public Session ResendSession(Session session)
        {
            if (session == null) return null;

            try
            {
                // 创建一个字典来存储额外的会话标志
                var sessionFlags = new System.Collections.Specialized.StringDictionary();
                sessionFlags.Add("X-ResentRequest", "true");

                // 使用FiddlerApplication.oProxy.SendRequestAndWait方法重发请求
                // 参数包括：原始请求头、请求体字节、会话标志和超时时间
                Session newSession = FiddlerApplication.oProxy.SendRequestAndWait(
                    session.oRequest.headers,    // 原始请求头
                    session.requestBodyBytes,    // 原始请求体
                    sessionFlags,                // 会话标志
                    null                         // 使用默认超时时间
                );

                // 检查新会话是否创建成功
                return newSession;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"重发会话失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 导出会话到文件
        /// </summary>
        /// <param name="sessions">要导出的会话集合</param>
        /// <param name="filePath">导出文件路径</param>
        /// <returns>导出是否成功</returns>
        public bool ExportSessions(IEnumerable<Session> sessions, string filePath)
        {
            if (sessions == null || !sessions.Any() || string.IsNullOrEmpty(filePath))
                return false;

            try
            {
                // 使用Fiddler的导出功能
                return Utilities.WriteSessionArchive(filePath, sessions.ToArray(), "", false);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"导出会话失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 从文件导入会话
        /// </summary>
        /// <param name="filePath">导入文件路径</param>
        /// <returns>导入的会话集合</returns>
        public IEnumerable<Session> ImportSessions(string filePath)
        {
            if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
                return Enumerable.Empty<Session>();

            try
            {
                string sazVersion = "";
                // 使用Fiddler的导入功能
                Session[] importedSessions = Utilities.ReadSessionArchive(filePath, out sazVersion);
                return importedSessions ?? Enumerable.Empty<Session>();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"导入会话失败: {ex.Message}");
                return Enumerable.Empty<Session>();
            }
        }

        /// <summary>
        /// 删除指定的会话
        /// </summary>
        /// <param name="sessions">要删除的会话集合</param>
        /// <returns>成功删除的会话数量</returns>
        public int RemoveSessions(IEnumerable<Session> sessions)
        {
            if (sessions == null) return 0;

            int removedCount = 0;
            _sessionsLock.EnterWriteLock();
            try
            {
                foreach (var session in sessions)
                {
                    if (_sessions.Remove(session))
                    {
                        removedCount++;
                    }
                }

                if (removedCount > 0)
                {
                    // 强制垃圾回收
                    GC.Collect();
                    System.Diagnostics.Debug.WriteLine($"已删除 {removedCount} 个会话，当前会话数: {_sessions.Count}");
                }
            }
            finally
            {
                _sessionsLock.ExitWriteLock();
            }

            return removedCount;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _sessionsLock?.Dispose();
        }
    }
}